﻿using Furion.DataEncryption;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Admin.Core;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using SqlSugar;
using Admin.Util;
using Furion;
using System.Linq;

namespace Admin.Application.BaseManage
{
    /// <summary>
    /// 授权服务
    /// </summary>
    [ApiDescriptionSettings(ApiGroupConsts.USER_CENTER, Name = "auth", Order = 100), ServiceFilter(typeof(LogHandler))]
    public class AuthorizeService : IAuthorizeService, IDynamicApiController, ITransient
    {
        /// <summary>
        /// 用户仓储
        /// </summary>
        private readonly ISqlSugarRepository<BaseUser> repository;
        private readonly ISqlSugarClient db;

        /// <summary>
        /// 用户管理类
        /// </summary>
        private readonly IOperator _operator;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="dbRepository"></param>
        /// <param name="myOperator"></param>
        public AuthorizeService(ISqlSugarRepository<BaseUser> dbRepository
            , IOperator myOperator)
        {
            repository = dbRepository;
            db = repository.Context;
            _operator = myOperator;
        }

        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="httpContextAccessor"></param>
        /// <param name="input"></param>
        /// <remarks>
        /// 用户名/密码：admin/admin
        /// </remarks>
        /// <returns></returns>
        [AllowAnonymous, ApiDescriptionSettings(Order = 100)]
        public async Task<object> LoginAsync([FromServices] IHttpContextAccessor httpContextAccessor, [Required] LoginInput input)
        {
            // 加密密码
            JsEncryptHelper newRsa = new JsEncryptHelper();
            var password = newRsa.Decrypt(input.Password);
            var encryptPassword = MD5Encryption.Encrypt(password);

            // 判断用户名或密码是否正确
            var user = await db.Queryable<BaseUser>().FirstAsync(u => u.Account.Equals(input.Account) && u.Password.Equals(encryptPassword));
            _ = user ?? throw Oops.Oh(SystemErrorCodes.u1000);

            // 更新登录时间
            user.SigninedTime = DateTime.Now;
            user.SigninedIP = NetHelper.Ip;
            await db.Updateable(user).UpdateColumns(it => new { it.SigninedTime, it.SigninedIP }).EnableDiffLogEvent("用户登录").ExecuteCommandAsync();

            // 映射结果
            var output = user.Adapt<LoginOutput>();

            // 生成 token
            var accessToken = output.AccessToken = JWTEncryption.Encrypt(new Dictionary<string, object>
            {
                { "UserId",user.Id },
                { "Account",user.Account }
            });

            output.TokenExpireAt = App.Configuration["TokenExpireAt"].ToInt();
            // 生成 刷新token
            var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken, output.TokenExpireAt);

            // 设置 Swagger 自动登录
            httpContextAccessor.SigninToSwagger(accessToken);

            // 设置刷新 token
            httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken;

            var securitiesList = await _operator.GetSecuritiesAsync(user.Id);
            var permissions = securitiesList.Where(x => x.MenuType == MenuType.权限).Select(x=>x.Perms).ToList();
            var resObj = new
            {
                UserInfo = output,
                Permissions = permissions
            };

            return resObj;
        }

        [SecurityDefine(SecurityConsts.ROLE_SERVICE_LIST)]
        public string GetList(int s, string a)
        {
            return $"{s}{a}";
        }
        public string UpdateList(int aaaaa)
        {
            return $"{aaaaa.ToString()}";
        }
        public string DeleteForm(int s, string a)
        {
            return $"{s}{a}";
        }
    }
}